package hjw.com.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

/**
 * <p>Project:Academic - SecurityConfig
 *
 * @author IvanWei玮 -- maste
 * @version 1.0
 * @DataTime 2025/1/20 14:13
 * @since 1.8
 */
@Configuration   // 将 SecurityConfig 创建对象 --->IOC
@EnableWebSecurity
@SuppressWarnings("all")
//请求先到 SecurityConfig 过滤一下， 才会到控制器
//如果登录请求， 就会找UserDetailsService 的 Bean
public class SecurityConfig {  //se-cu-ri-ty 安全

    @Autowired
    public SecurityConfig(AuthenticationConfiguration authenConfig) {
        System.out.println("SecurityConfig 创建对象");
        this.authenConfig = authenConfig;
    }
    //获取认证管理器， 简单而言就是比对密码：
    // 1. 主动调用 loadUserByUsername( ...)  访问 t_user
    // 2. 主动比对账号密码
    //        - 成功: successfulAutentication
    //        - 不成功: unsuccessfulAuthentication
    private final AuthenticationConfiguration authenConfig;
    //获取认证管理器的配置类， 再去获取认证管理器

    @Bean
    AuthenticationManager authenticationManager() throws Exception {
        return authenConfig.getAuthenticationManager();
    }

    //There is no PasswordEncoder mapped for the id "null"
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();  //加盐加密
    }

    //权限
    @Bean  // http.build() 返回值装配到 IOC 容器
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        //权限判断， 是在过滤器的最后一环执行
        //session 有 Autentication 对象
        http.authorizeRequests()
                .antMatchers("/api/public/**").permitAll()  //无需登录，就可以访问的
                .antMatchers("/static/**","/**","/*.html").permitAll()
                .antMatchers("/static/**","/css/**.css","/fonts/**.woff","/fonts/**.ttf","/img/**.img","/js/**.js","/*.html").permitAll()
                .antMatchers("/api/login").permitAll()  //无需登录，就可以访问的
                .antMatchers("/go2login").permitAll()  //无需登录，就可以访问的
                .antMatchers("/api/user/**")
                .hasAuthority("usr")
                .anyRequest().authenticated()   //authened 已经登录成功后才能访问 /api/user/改密码
                .and()
                .formLogin()   //  /login
                // .loginPage("/go2login")  // 显示 login.html    session 模式其效果
//                .loginProcessingUrl("/api/login")   //重要  session 模式其效果
                .permitAll()   //  无需登录可以访问（permit 允许）
                .and()
                .csrf().disable()
                //在这个后面加  不走 session, 我要走自己方式 (Token)
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilter( new JwtLoginFilter(authenConfig.getAuthenticationManager()))
                //添加自己的登录方式(api/login2, 并且传递 认证管理器
                .addFilter( new JwtAuthenFilter(authenConfig.getAuthenticationManager()))
                .exceptionHandling().authenticationEntryPoint(new JwtAuthEntryPoint());
        //添加自己的授权过滤器, 负责拦截每次业务请求

        //public HttpSecurity addFilter(Filter filter)

        return http.build();
    }

    /*
    用户信息， 内存用户信息 UserDetailsService  User 用户  Details(具体信息)  Service 服务
    @Bean
    UserDetailsService userDetailsService() {

    }*/
}
